﻿#include "serialportdatasource.h"
#include "../log/logger.h"

#if __QT_ENV_US__

#elif defined(Q_OS_LINUX)
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#else

#endif

//该数据源使用同步读写的方式
SerialPortDataSourceTool::SerialPortDataSourceTool(const char *path_utf, int baudrate)
{
	this->initial(path_utf, baudrate);
}

SerialPortDataSourceTool::~SerialPortDataSourceTool()
{
	this->destroy();
}
bool SerialPortDataSourceTool::IsEof()
{
	return false;
}
#ifdef __QT_ENV_US__

#elif defined(WIN32)
#define FUNCTION1
#ifdef FUNCTION1
void SerialPortDataSourceTool::initial(const char *path_utf, int baudrate)
{
	openSys(path_utf, baudrate);
}
void SerialPortDataSourceTool::destroy()
{
	this->Close();
}

void SerialPortDataSourceTool::openSys(const char *path_utf, int baudrate)
{
	BOOL result = false;
	msp = CreateFileA(path_utf,  /** 设备名,COM1,COM2等 */
		GENERIC_READ | GENERIC_WRITE, /** 访问模式,可同时读写 */
		0,                            /** 共享模式,0表示不共享 */
		NULL,                         /** 安全性设置,一般使用NULL */
		OPEN_EXISTING,                /** 该参数表示设备必须存在,否则创建失败 */
		0,
		0);
	if (msp == INVALID_HANDLE_VALUE)
	{
		LOG(LERROR) << "open com faild:" << path_utf << ",baudrate:" << baudrate;
		TRACE("open failed：%s,rate:%d\r\n", path_utf, baudrate);
		CloseHandle(msp);
		return;
	}
	else 
	{
		LOG(INFO) << "open com success:" << path_utf << ",baudrate：" << baudrate;
		TRACE("open success：%s,rate:%d\r\n", path_utf, baudrate);
	}
	//配置串口
	COMMTIMEOUTS  CommTimeouts;
	CommTimeouts.ReadIntervalTimeout = 0;
	CommTimeouts.ReadTotalTimeoutMultiplier = 1;
	CommTimeouts.ReadTotalTimeoutConstant = 0.5;
	CommTimeouts.WriteTotalTimeoutMultiplier = 1;
	CommTimeouts.WriteTotalTimeoutConstant = 1;
	result = SetCommTimeouts(msp, &CommTimeouts);
	if (!result)
	{
		LOG(LERROR) << "SetCommTimeouts Faild：" << GetLastError() << ",name:" << path_utf << ",波特率：" << baudrate;
		TRACE("get com state failed：%s,rate:%d", path_utf, baudrate);
	}

	char szDCBparam[50];
	sprintf_s(szDCBparam, "baud=%d parity=%c data=%d stop=%d", baudrate, 'N', 8, 1);
	DCB  dcb;

	// 将ANSI字符串转换为UNICODE字符串
	DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, szDCBparam, -1, NULL, 0);
	wchar_t *pwText = new wchar_t[dwNum];
	if (!MultiByteToWideChar(CP_ACP, 0, szDCBparam, -1, pwText, dwNum))
	{

	}

	/** 获取当前串口配置参数,并且构造串口DCB参数 */
	result = GetCommState(msp, &dcb) && BuildCommDCB(pwText, &dcb);
	if (!result)
	{
		LOG(LERROR) << "获取com口状态失败：" << GetLastError() << ",name:" << path_utf << ",波特率：" << baudrate;
		TRACE("get com state failed：%s,rate:%d", path_utf, baudrate);
	}
	/** 释放内存空间 */
	DELETES(pwText);

	/** 使用DCB参数配置串口状态 */
	result = SetCommState(msp, &dcb);
	if (!result)
	{
		LOG(LERROR) << "设置com DCB口状态失败：" << GetLastError() << ",name:" << path_utf << ",波特率：" << baudrate;
		TRACE("set com bcd state failed：%s,rate:%d", path_utf, baudrate);
	}
	result = SetupComm(msp, 5 * 1024, 1024);
	if (!result)
	{
		LOG(LERROR) << "SetupComm faild：" << GetLastError() << ",name:" << path_utf << ",波特率：" << baudrate;
		TRACE("set com bcd state failed：%s,rate:%d", path_utf, baudrate);
	}

	/**  清空串口缓冲区 */
	result = PurgeComm(msp, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
	if (!result)
	{
		LOG(LERROR) << "情况com 缓存区失败：" << GetLastError() << ",name:" << path_utf << ",波特率：" << baudrate;
		TRACE("clear com cache failed：%s,rate:%d", path_utf, baudrate);
	}
}

void SerialPortDataSourceTool::Send(const char *message, int count)
{
	try
	{
		LPDWORD byteswrite = 0;//已经读出来的字节数
		BOOL res = WriteFile(msp, (unsigned char*)message, count, byteswrite, NULL);
	}
	catch (const std::exception&)
	{
	}
}

int SerialPortDataSourceTool::FetchNext(char *buf, int bufsize)
{
	// 数据刷新略显慢
	DWORD bytesRead = 0;//已经读出来的字节数
	BOOL res = ReadFile(msp, buf, bufsize, &bytesRead, NULL);
	return (int)bytesRead;
}
void SerialPortDataSourceTool::Close()
{
	int ret = CloseHandle(msp);
}
#else

#endif
#endif
